/*******************************************************************************
*	                           oled spi.c
*******************************************************************************/
#include "bsp.h"
#include "pincfg.h"
#include "common.h"

#define SPI_PORT SPI1
#define ISR_IRQn SPI1_IRQn

/*****************************************************************************
* @brief   hal init.
*
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void bsp_spi_init(void)
{
	spi_parameter_struct cfg;
	intx_alloc();

	// 开启时钟
	intx_disable();

	rcu_periph_clock_enable(RCU_SPI1);
	rcu_periph_reset_enable(RCU_SPI1RST);
	rcu_periph_reset_disable(RCU_SPI1RST);

	intx_enable();

	// SPI 配置
	cfg.device_mode = SPI_MASTER;
	cfg.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
	cfg.frame_size = SPI_FRAMESIZE_8BIT;
	cfg.nss = SPI_NSS_SOFT;
	cfg.endian = SPI_ENDIAN_MSB;
	cfg.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
	cfg.prescale = SPI_PSC_4;

	spi_init(SPI_PORT, &cfg);
	
	spi_enable(SPI_PORT);
	
	bsp_spi_cs(1);
}

/*****************************************************************************
* @brief   cs ctr.
*
* @param   none
*
* @return  none
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void bsp_spi_cs(uint8_t st)
{
	spiss.out(st);
}


/*****************************************************************************
* @brief   spi delay.
*****************************************************************************/
#define spi_read_delay() NOP4()
#define is_spi_rx_ready() (SPI_STAT(SPI_PORT)&SPI_STAT_RBNE)
#define spi_rx_reset()                       \
	while (is_spi_rx_ready())                \
	{                                        \
		volatile uint32_t rd = SPI_DATA(SPI_PORT); \
	}

#define spi_send(dat) SPI_DATA(SPI_PORT) = dat
#define is_spi_tx_full() ((SPI_STAT(SPI_PORT)&SPI_STAT_TBE)==0)
#define is_spi_tx_empty() (SPI_STAT(SPI_PORT)&SPI_STAT_TBE)
#define spi_read() SPI_DATA(SPI_PORT)
#define is_spi_busy() (SPI_STAT(SPI_PORT)&SPI_STAT_TRANS)
	
/*****************************************************************************
* @brief   spi data read.
*****************************************************************************/
uint8_t bsp_spi_rb(void)
{
	spi_rx_reset();

	//send data
	spi_send(0xFF);
	spi_read_delay();

	//wait for trans complete
	while (!is_spi_rx_ready())
		;

	//read data
	return (spi_read());
}

void bsp_spi_wb(uint8_t dataW)
{
	volatile uint8_t rb;

	spi_rx_reset();

	//send data
	spi_send(dataW);
	spi_read_delay();

	//wait for trans complete
	while (!is_spi_rx_ready())
		;

	//read data
	rb = spi_read();
}

/*****************************************************************************
* @brief   spi data write.
*****************************************************************************/
uint8_t bsp_spi_write(const uint8_t *dataw, uint32_t Len)
{
	while (Len--)
	{
		//send data
		spi_send(*dataw++);

		spi_read_delay();

		while (is_spi_tx_full())
		{
		}
		
	}

	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy() || !is_spi_tx_empty())
	{
	}

	spi_rx_reset();

	return (0);
}

/*****************************************************************************
* @brief   spi data read.
*****************************************************************************/
uint8_t bsp_spi_read(uint8_t *datar, uint32_t Len)
{
	uint32_t rcnt = 0;

	spi_rx_reset();

	while (Len--)
	{
		//send data
		spi_send(0xFF);

		spi_read_delay();

		while (!is_spi_rx_ready())
		{
		}

		datar[rcnt++] = spi_read();
	}

	return 0;
}

/*****************************************************************************
* @brief   spi data write.
*****************************************************************************/
uint8_t bsp_spi_write_B32(const uint32_t *dataw, uint32_t Len)
{
	while (Len--)
	{
		dword_tt dat;
		
		dat.uval = *dataw++;
		
		//send data
		spi_send(dat.v[3]);
		spi_read_delay();
		while (is_spi_tx_full()){}
		
		spi_send(dat.v[2]);
		spi_read_delay();
		while (is_spi_tx_full()){}
			
		spi_send(dat.v[1]);
		spi_read_delay();
		while (is_spi_tx_full()){}
			
		spi_send(dat.v[0]);
		spi_read_delay();
		while (is_spi_tx_full()){}
	}

	spi_read_delay();

	//wait for trans complete
	while (is_spi_busy() || !is_spi_tx_empty())
	{
	}

	spi_rx_reset();

	return (0);
}

/*****************************************************************************
* @brief   spi data read.
*****************************************************************************/
uint8_t bsp_spi_read_B32(uint32_t *datar, uint32_t Len)
{
	uint32_t rcnt = 0;

	spi_rx_reset();

	while (Len--)
	{
		dword_tt dat;
		
		//send data
		spi_send(0xFF);
		spi_read_delay();
		while (!is_spi_rx_ready()){}
		dat.v[3] = spi_read();
			
		spi_send(0xFF);
		spi_read_delay();
		while (!is_spi_rx_ready()){}
		dat.v[2] = spi_read();

		spi_send(0xFF);
		spi_read_delay();
		while (!is_spi_rx_ready()){}
		dat.v[1] = spi_read();

		spi_send(0xFF);
		spi_read_delay();
		while (!is_spi_rx_ready()){}
		dat.v[0] = spi_read();			

		datar[rcnt++] = dat.uval;
	}

	return 0;
}

